AWS EC2 上の Python から BigQuery にデータをロードしてみた
こんにちは、みかみです。
GCP & BigQuery 勉強中です。
業務では Python をメインに使用しています。BigQuery にも Python 経由でアクセスしたい!
やりたいこと
- EC2 から Python で BigQuery にアクセスしたい
- Python コードでファイルデータを BigQuery にロードしたい
やってみた
GCP の準備
クイックスタートに従って、APIを有効にした後、認証情報の設定に進みます。
認証情報設定画面で「必要な認証情報」ボタンをクリック。
「プロジェクトへの認証情報の追加」画面で、「サービス アカウント名」に任意の文字列を入力し、「役割」で「Project」「オーナー」を選択します。「キーのタイプ」は「JSON」のまま「次へ」ボタンをクリック。
サービスアカウントキー作成完了ポップアップが表示され、キーファイルがPCにダウンロードされました。
作成したサービスアカウントは、GCP コンソール「IAMと管理」の「サービスアカウント」から、確認、編集、削除可能なようです。
EC2の準備
キーファイルパスの設定
EC2(Amazon Linux 2) を立ち上げて、先ほど取得したキーファイルを配置したパスを、環境変数 GOOGLE_APPLICATION_CREDENTIALS に設定します。
再ログインした時に設定しなおす手間を省くため、~/.bash_profile に以下を追記しました。
export GOOGLE_APPLICATION_CREDENTIALS="/home/ec2-user/cm-da-mikami-yuki.json"
プロファイルを読み込みなおして確認してみると・・・
[ec2-user@ip-172-31-31-170 ~]$ source ~/.bash_profile [ec2-user@ip-172-31-31-170 ~]$ echo $GOOGLE_APPLICATION_CREDENTIALS /home/ec2-user/cm-da-mikami-yuki.json
ちゃんと環境変数が設定されました。
クライアント ライブラリをインストール
Python の BigQuery 操作用ライブラリ google-cloud-bigquery をインストールします。
サポートされる Python バージョンは 3.5 以上とのことです。
Amazon Linux 2 にはデフォルトで 3系 の Python が入っていないので、まずは Python3 と pip をインストールします。
[ec2-user@ip-172-31-31-170 ~]$ sudo yum install python3 Loaded plugins: extras_suggestions, langpacks, priorities, update-motd amzn2-core | 2.4 kB 00:00 Resolving Dependencies (省略) Installed: python3.x86_64 0:3.7.4-1.amzn2.0.3 Dependency Installed: python3-libs.x86_64 0:3.7.4-1.amzn2.0.3 python3-pip.noarch 0:9.0.3-1.amzn2.0.1 python3-setuptools.noarch 0:38.4.0-3.amzn2.0.6 Complete! [ec2-user@ip-172-31-31-170 ~]$ curl -O https://bootstrap.pypa.io/get-pip.py % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1734k 100 1734k 0 0 18.8M 0 --:--:-- --:--:-- --:--:-- 18.8M [ec2-user@ip-172-31-31-170 ~]$ python3 get-pip.py --user Collecting pip Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB) |████████████████████████████████| 1.4MB 3.3MB/s Collecting wheel Downloading https://files.pythonhosted.org/packages/00/83/b4a77d044e78ad1a45610eb88f745be2fd2c6d658f9798a15e384b7d57c9/wheel-0.33.6-py2.py3-none-any.whl Installing collected packages: pip, wheel Successfully installed pip-19.3.1 wheel-0.33.6
インストール完了。バージョンを確認してみます。
[ec2-user@ip-172-31-31-170 ~]$ pip -V pip 19.3.1 from /home/ec2-user/.local/lib/python3.7/site-packages/pip (python 3.7) [ec2-user@ip-172-31-31-170 ~]$ python --version Python 2.7.16 [ec2-user@ip-172-31-31-170 ~]$ python3 --version Python 3.7.4
普通の python コマンドだと 2系 が動いてしまうので、デフォルトを3系にするよう、.bash_profile に alias を追加します。
alias python=python3
確認してみると・・・
[ec2-user@ip-172-31-31-170 ~]$ source .bash_profile [ec2-user@ip-172-31-31-170 ~]$ python --version Python 3.7.4
デフォルトで 3系 が動くようになりました。
続いて virtualenv で google-cloud-bigquery をインストールします。
[ec2-user@ip-172-31-31-170 ~]$ pip install virtualenv --user Collecting virtualenv Using cached https://files.pythonhosted.org/packages/62/77/6a86ef945ad39aae34aed4cc1ae4a2f941b9870917a974ed7c5b6f137188/virtualenv-16.7.8-py2.py3-none-any.whl Installing collected packages: virtualenv Successfully installed virtualenv-16.7.8 [ec2-user@ip-172-31-31-170 ~]$ virtualenv test_bq Using base prefix '/usr' No LICENSE.txt / LICENSE found in source New python executable in /home/ec2-user/test_bq/bin/python3 Also creating executable in /home/ec2-user/test_bq/bin/python Installing setuptools, pip, wheel... done. [ec2-user@ip-172-31-31-170 ~]$ source test_bq/bin/activate (test_bq) [ec2-user@ip-172-31-31-170 ~]$ test_bq/bin/pip install google-cloud-bigquery Collecting google-cloud-bigquery (省略) Successfully built googleapis-common-protos Installing collected packages: pyasn1, rsa, pyasn1-modules, cachetools, six, google-auth, pytz, protobuf, googleapis-common-protos, urllib3, idna, certifi, chardet, requests, google-api-core, google-cloud-core, google-resumable-media, google-cloud-bigquery Successfully installed cachetools-3.1.1 certifi-2019.11.28 chardet-3.0.4 google-api-core-1.14.3 google-auth-1.7.1 google-cloud-bigquery-1.22.0 google-cloud-core-1.0.3 google-resumable-media-0.5.0 googleapis-common-protos-1.6.0 idna-2.8 protobuf-3.11.0 pyasn1-0.4.8 pyasn1-modules-0.2.7 pytz-2019.3 requests-2.22.0 rsa-4.0 six-1.13.0 urllib3-1.25.7
無事、インストールできました。
Python コードから BigQuery にアクセスしてみる
テーブルデータ参照
BigQuery のテーブルデータを参照するサンプルコードをいただいてきて、クエリ部分のみ既存の自分の環境に合わせて修正しました。
from google.cloud import bigquery client = bigquery.Client() # Perform a query. QUERY = ( 'SELECT name FROM `cm-da-mikami-yuki-258308.test_s3.pref` ' 'WHERE code = 15 ') query_job = client.query(QUERY) # API request rows = query_job.result() # Waits for query to finish for row in rows: print(row.name)
実行してみると・・・
(test_bq) [ec2-user@ip-172-31-31-170 ~]$ python test_select.py 新潟県
データが取得できました!
ファイルデータをロード
こちらからいただいてきた、アメリカの赤ちゃんの名前ファイルの拡張子を .csv に変更&ヘッダ行を追加して EC2 に配置しました。
Python で、データセットとテーブルを作成してからファイルデータをロードします。
from google.cloud import bigquery # データセット作成 client = bigquery.Client() dataset_id = "{}.test_dataset".format(client.project) dataset = bigquery.Dataset(dataset_id) dataset.location = "asia-northeast1" dataset = client.create_dataset(dataset) print("Created dataset {}.{}".format(client.project, dataset.dataset_id)) # テーブル作成 table_id = "{}.{}.names_1880".format(client.project, dataset.dataset_id) schema = [ bigquery.SchemaField("name", "STRING", mode="REQUIRED"), bigquery.SchemaField("gender", "STRING", mode="REQUIRED"), bigquery.SchemaField("count", "INTEGER", mode="REQUIRED"), ] table = bigquery.Table(table_id, schema=schema) table = client.create_table(table) print( "Created table {}.{}.{}".format(table.project, table.dataset_id, table.table_id) ) # データロード filename = '/home/ec2-user/data/yob1880.csv' dataset_id = dataset_id.split(".")[-1] table_id = table_id.split(".")[-1] dataset_ref = client.dataset(dataset_id) table_ref = dataset_ref.table(table_id) job_config = bigquery.LoadJobConfig() job_config.source_format = bigquery.SourceFormat.CSV job_config.skip_leading_rows = 1 job_config.autodetect = False with open(filename, "rb") as source_file: job = client.load_table_from_file(source_file, table_ref, job_config=job_config) job.result() print("Loaded {} rows into {}:{}.".format(job.output_rows, dataset_id, table_id))
実行してみると・・・
(test_bq) [ec2-user@ip-172-31-31-170 ~]$ python test_load.py Created dataset cm-da-mikami-yuki-258308.test_dataset Created table cm-da-mikami-yuki-258308.test_dataset.names_1880 Loaded 2000 rows into test_dataset:names_1880.
ロード完了したようです。
GCP コンソールからも、ロードされたデータを確認できました。
まとめ(所感)
前回ためした bq コマンドラインを使って shell スクリプトも書けると思いますが、Python からのアクセスで、システムイメージが広がりました。
BigQuery クライアントライブラリは、Python の他にも Ruby や NODE.JS、JAVA など揃っていて、システム実装には困らなそう。
API まわりの理解を深めて、ライブラリを自分で拡張してみるのも面白そうです。